package com.xytc.company.company_backend.adminEndPoint.service;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xytc.company.company_backend.adminEndPoint.entity.dao.FoodRepositoryDao;
import com.xytc.company.company_backend.adminEndPoint.entity.rto.FoodRto;
import com.xytc.company.company_backend.adminEndPoint.mapper.IFoodManageMapper;
import com.xytc.company.company_backend.common.FileConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class FoodManageServiceImpl {

    @Autowired
    private IFoodManageMapper foodManageMapper;

    /**
     * 每次 更新菜品或店铺信息时，接口入参会传递所有图片 信息，此时需要根据当前 图片存储路径下的图片 和 入参中的图片，
     * 来判断是否需要新增或移除图片（每次菜品或店铺信息更新时，都有可能新增或更新，移除某些图片）
     * @param originalFileNames 接口调用之前，菜品或店铺的 图片信息
     * @param newFileNames 接口调用时的入参，可能本次接口调用，图片没有更新，此时 参数2和参数1的值相同
     */
    public void updateImageFilesAndBuildImageUrls(List<String> originalFileNames,
                                                          List<String> newFileNames, String partDir, List<String> imageUrls) {
        // 1. 挑出 orginalFileNames中，不在 newFileNames 中的文件，则表示在本次接口调用时，被替换的，需要被删除的图片
        List<String> needDeletedFileNames = originalFileNames.stream().filter(item -> !newFileNames.contains(item)).collect(Collectors.toList());
        // 2. 挑出 newFileNames中，不在 originalFileNames中的文件，则表示在本次接口调用时，新增的图片
        List<String> newAddedFileNames = newFileNames.stream().filter(item -> !originalFileNames.contains(item)).collect(Collectors.toList());
        log.info("need deleted files: {}, need added files: {}", needDeletedFileNames, newAddedFileNames);
        // 3. 先删除被替换的图片
        needDeletedFileNames.forEach(fileName-> {
            Path filePath = Paths.get(FileConstants.IMAGE_UPLOAD_DIR, partDir, fileName);
            File file = filePath.toFile();
            if (file.exists()) {
                file.delete();
            }
        });
        // 4. 将新增的图片，移动到正式路径下
        newAddedFileNames.forEach(fileName -> {
            String newAddFilePath =  FileConstants.FILE_UPLOAD_TEMP_DIR + File.separator + fileName;
            String newFileFinalUrl = moveTemp2FinalDirAndBuildFinalUrl(newAddFilePath, partDir);
            // 将入参中，新增图片的文件路径移除
            imageUrls.removeIf(imageUrl->imageUrl.contains(fileName));
            // 替换成 url
            imageUrls.add(newFileFinalUrl);
        });
    }


    /**
     * 将 图片从临时目录移动到 正式目录，并更新图片的url，入参中的images 数组，只是图片在临时目录的 文件路径，而不是可以被访问的url
     * @param tempPath 图片的临时路径
     * @param partDir 图片存放的部分目录，文件完整路径，出去 base路径，和 文件名，中间部分的路径
     * @return
     */
    public String moveTemp2FinalDirAndBuildFinalUrl(String tempPath, String partDir) {

        // 将菜品的图片从临时目录移动到正式目录
        String fileName = tempPath.substring(tempPath.lastIndexOf(File.separator) + 1);
        File tempImageFile = new File(tempPath);
        Path finalImageFilePath = Paths.get(FileConstants.IMAGE_UPLOAD_DIR, partDir, fileName);
        // 必须得提前创建文件路径中，不存在的文件夹，当前jdk的io类中，没有提供根据文件路径，自动创建中间文件夹的方法
        File finelImageDir = Paths.get(FileConstants.IMAGE_UPLOAD_DIR, partDir).toFile();
        if (!finelImageDir.exists()) {
            finelImageDir.mkdirs();
        }
        String finalImageUrl = FileConstants.IMAGE_URL_BASE + partDir.replace("\\","/") + fileName; // windows系统中partDir分隔符是\，linux系统是/，如果是linux系统，则replace不会匹配到\，保持原样不变
        if (tempImageFile.exists()) {
            try {
                Files.move(Paths.get(tempPath), finalImageFilePath);
                log.info("move temp image file: {} from temp upload dir to image-resource dir: {} done, url: {}",
                        tempPath, finalImageFilePath, finalImageUrl);
            } catch (IOException e) {
                log.error("将临时文件移动到正式目录失败，error: {}", e);
                throw new RuntimeException(e);
            }

        } else {
            log.error("temp image file: {} not exist", tempPath);
        }
        return finalImageUrl;
    }


    /**
     * 当新增菜品或店铺时，将菜品或店铺图片从 临时目录移动到 正式目录
     * @param tempPath
     * @param imageDir
     */
    public void moveTemp2ImageDir(String tempPath, String imageDir) {
        String fileName = tempPath.substring(tempPath.lastIndexOf(File.separator) + 1);
        File tempImageFile = new File(tempPath);
        File finalImageFile = Paths.get(FileConstants.IMAGE_UPLOAD_DIR, imageDir, fileName).toFile();
        if (tempImageFile.exists()) {
            tempImageFile.renameTo(finalImageFile);
            log.info("move temp image file: {} from temp upload dir to image-resource dir: {} done",
                    tempPath, finalImageFile.getAbsolutePath());
        } else {
            log.error("temp image file: {} not exist", tempPath);
        }
    }

    public void updateImagesAndUpdateUrls(FoodRto foodRTO) {
        // 更新前，需要获取当前db中保存的菜品图片信息，根据db中保存的图片信息和接口入参的图片信息，判断是否需要更新图片
        List<FoodRepositoryDao> list = foodManageMapper.selectList(
                new LambdaQueryWrapper<FoodRepositoryDao>()
                        .eq(FoodRepositoryDao::getId, foodRTO.getId())
                        .eq(FoodRepositoryDao::getDelFlag,0)
                        .select(FoodRepositoryDao::getImages));
        if (list != null && !list.isEmpty()) {
            // 解析当前db中存放的菜品的图片信息
            List<String> originalFileUrls = JSONArray.parseArray(list.get(0).getImages(), String.class);
            List<String> originalFileNames = originalFileUrls.stream().map(
                    url -> url.substring(url.lastIndexOf(File.separator + 1))
            ).collect(Collectors.toList());
            // 解析参数中传递的图片信息，如果更新了图片，则 newFileUrls中既有 图片url也有新添加图片的文件路径
            List<String> newFileUrls = foodRTO.getImages().toJavaList(String.class);
            List<String> newFileNames = newFileUrls.stream().map(
                    url -> url.substring(url.lastIndexOf(File.separator + 1))
            ).collect(Collectors.toList());
            // 删除废弃的图片，将新增的图片，从临时目录移动到正式目录，并生成url
            String partDir = foodRTO.getStoreId() + File.separator + "foods" + File.separator;
            List<String> updatedImageUrls = foodRTO.getImages().toJavaList(String.class);
            updateImageFilesAndBuildImageUrls(originalFileNames, newFileNames, partDir, updatedImageUrls);
            // 将入参中的可能包含新增图片文件路径的url列表，更新成 全部的url列表
            foodRTO.setImages(new JSONArray(updatedImageUrls));
        } else {
            log.error("food repository 表中无法找到id为 {} 的记录, 不对菜品图片信息进行更新，可能会导致服务器上存放废弃的菜品图片", foodRTO.getId());
        }
    }
}
